#include <iostream>
#include <vector>
#include <type_traits>
#include <optional>
#include <version>

// 编译器标准信息结构体
struct CompilerInfo {
    const char* name;
    const char* version;
};

// 获取编译器信息
CompilerInfo getCompilerInfo() {
    CompilerInfo info = {"Unknown", "Unknown"};
    
    #if defined(__clang__)
    info.name = "Clang";
    info.version = __clang_version__;
    #elif defined(__GNUC__)
    info.name = "GCC";
    info.version = __VERSION__;
    #elif defined(_MSC_VER)
    info.name = "MSVC";
    // 将MSVC版本转换为可读格式
    if (_MSC_VER >= 1930) info.version = "2022+";
    else if (_MSC_VER >= 1920) info.version = "2019";
    else if (_MSC_VER >= 1910) info.version = "2017";
    #endif
    
    return info;
}

// 测试C++11特性
void testCPP11() {
    std::cout << "  [C++11 Tests]\n";
    
    // auto 类型推导
    auto num = 42;
    std::cout << "    auto: " << num << " (";
    if (num == 42) std::cout << "PASS";
    else std::cout << "FAIL";
    std::cout << ")\n";
    
    // 基于范围的for循环
    int sum = 0;
    int arr[] = {1, 2, 3};
    for (int n : arr) sum += n;
    std::cout << "    Range-based for: " << sum << " (";
    if (sum == 6) std::cout << "PASS";
    else std::cout << "FAIL";
    std::cout << ")\n";
    
    // nullptr
    int* ptr = nullptr;
    std::cout << "    nullptr: " << (ptr ? "FAIL" : "PASS") << "\n";
}

// 测试C++14特性
void testCPP14() {
    std::cout << "  [C++14 Tests]\n";
    
    // 泛型lambda
    auto generic_lambda = [](auto x, auto y) { return x + y; };
    int result = generic_lambda(3, 4);
    std::cout << "    Generic lambda: 3+4=" << result << " (";
    if (result == 7) std::cout << "PASS";
    else std::cout << "FAIL";
    std::cout << ")\n";
    
    // 二进制字面量
    int binary = 0b1101;
    std::cout << "    Binary literal: 0b1101=" << binary << " (";
    if (binary == 13) std::cout << "PASS";
    else std::cout << "FAIL";
    std::cout << ")\n";
}

// 测试C++17特性
void testCPP17() {
    std::cout << "  [C++17 Tests]\n";
    
    // 结构化绑定
    std::pair<int, std::string> p{42, "answer"};
    auto [num, str] = p;
    std::cout << "    Structured binding: " << num << "=" << str << " (";
    if (num == 42 && str == "answer") std::cout << "PASS";
    else std::cout << "FAIL";
    std::cout << ")\n";
    
    // std::optional
    std::optional<int> maybeInt;
    maybeInt = 100;
    std::cout << "    std::optional: ";
    if (maybeInt.has_value() && *maybeInt == 100) std::cout << "PASS";
    else std::cout << "FAIL";
    std::cout << "\n";
}

// 测试C++20特性
void testCPP20() {
    std::cout << "  [C++20 Tests]\n";
    
    // 概念约束 (使用SFINAE检测)
    auto check_concept = []() -> std::enable_if_t<__cpp_concepts >= 201907L, bool> {
        return true;
    };
    auto fallback = []() -> bool { return false; };
    
    bool concepts_supported = false;
    if constexpr (__cpp_concepts >= 201907L) {
        concepts_supported = check_concept();
    } else {
        concepts_supported = fallback();
    }
    
    std::cout << "    Concepts: " << (concepts_supported ? "PASS" : "NOT SUPPORTED") << "\n";
    
    // 三路比较运算符 (<=>)
    #if __has_include(<compare>)
    auto compare = [](int a, int b) {
        if constexpr (__cpp_impl_three_way_comparison >= 201907L) {
            return (a <=> b) == 0;
        }
        return a == b;
    };
    std::cout << "    3-way comparison (<=>): " 
              << (compare(5, 5) ? "PASS" : "FAIL") << "\n";
    #else
    std::cout << "    3-way comparison: NOT SUPPORTED\n";
    #endif
}

// 测试C++23特性
void testCPP23() {
    std::cout << "  [C++23 Tests]\n";
    
    // if consteval
    auto test_consteval = []{
        #if __cpp_if_consteval >= 202106L
        if consteval {
            return "consteval";
        } else {
            return "runtime";
        }
        #else
        return "NOT SUPPORTED";
        #endif
    };
    
    std::cout << "    if consteval: " << test_consteval() << "\n";
    
    // std::print (如果支持)
    #if __has_include(<print>)
    std::cout << "    std::print: SUPPORTED\n";
    #else
    std::cout << "    std::print: NOT SUPPORTED\n";
    #endif
}

// 测试C++26特性
void testCPP26() {
    std::cout << "  [C++26 Tests]\n";
    
    // 检查反射提案状态
    #if __cpp_reflection >= 202306L
    std::cout << "    Reflection: EXPERIMENTAL SUPPORT\n";
    #else
    std::cout << "    Reflection: NOT SUPPORTED\n";
    #endif
    
    // 检查模式匹配状态
    #if __cpp_match >= 202306L
    std::cout << "    Pattern Matching: EXPERIMENTAL SUPPORT\n";
    #else
    std::cout << "    Pattern Matching: NOT SUPPORTED\n";
    #endif
}

int main() {
    // 获取编译器信息
    CompilerInfo compiler = getCompilerInfo();
    std::cout << "Compiler: " << compiler.name 
              << " (" << compiler.version << ")\n";
    
    // 获取语言标准
    #if defined(_MSVC_LANG)
    long standard = _MSVC_LANG;
    #elif defined(__cplusplus)
    long standard = __cplusplus;
    #else
    long standard = 0;
    #endif
    
    // 标准版本映射
    const int numStandards = 7;
    const long stdCode[numStandards] = { 
        199711L, 201103L, 201402L, 201703L, 202002L, 202302L, 202612L
    };
    const char* stdName[numStandards] = { 
        "Pre-C++11", "C++11", "C++14", "C++17", "C++20", "C++23", "C++26" 
    };

    // 检测并显示标准
    bool found = false;
    for (int i = 0; i < numStandards; ++i) {
        if (standard == stdCode[i]) {
            std::cout << "\nLanguage Standard: " << stdName[i] 
                      << " (" << standard << "L)\n\n";
            found = true;
            break;
        }

        if (standard < stdCode[i]) {
            std::cout << "\nLanguage Standard: Preview of " << stdName[i]
                      << " (" << standard << "L)\n\n";
            found = true;
            break;
        }
    }
    
    if (!found) {
        std::cout << "\nUnknown Language Standard: " << standard << "L\n\n";
    }

    // 运行各版本特性测试
    if (standard >= 201103L) testCPP11();
    if (standard >= 201402L) testCPP14();
    if (standard >= 201703L) testCPP17();
    if (standard >= 202002L) testCPP20();
    if (standard >= 202302L) testCPP23();
    if (standard >= 202612L) testCPP26();
    
    std::cout << "\nNote: Some features may require additional compiler flags\n";
    return 0;
}